home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / graphic / frasr182.zip / CALCMAND.ASM < prev    next >
Assembly Source File  |  1992-08-19  |  28KB  |  820 lines

  1. ;    CALCMAND.ASM - Mandelbrot/Julia Set calculation Routines
  2.  
  3. ;    This module runs as part of an overlay with calcfrac.c.
  4. ;    It must not be called from anywhere other than calcfrac.
  5.  
  6. ;    The routines in this code perform Mandelbrot and Julia set
  7. ;    calculations using 32-bit integer math as opposed to the
  8. ;    "traditional" floating-point approach.
  9.  
  10. ;    This code relies on several tricks to run as quickly as it does.
  11.  
  12. ;    One can fake floating point arithmetic by using integer
  13. ;    arithmetic and keeping track of the implied decimal point
  14. ;    if things are reasonable -- and in this case, they are.
  15. ;    I replaced code that looked like: z = x*y with code that
  16. ;    looks like:
  17. ;            ix = x * ifudge         (outside the loops)
  18. ;            iy = y * ifudge
  19. ;            ....
  20. ;            iz = (ix * iy) / ifudge     (inside the loops)
  21. ;    (and keep remembering that all the integers are "ifudged" bigger)
  22.  
  23. ;    The 386 has native 32-bit integer arithmetic, and (briefly) keeps
  24. ;    64-bit values around after 32-bit multiplies.    If the result is
  25. ;    divided down right away, you've got 64-bit arithmetic.   You just
  26. ;    have to ensure that the result after the divide is <= 32 bits long.
  27. ;    CPUs predating the 386 have to emulate 32-bit arithmetic using
  28. ;    16-bit arithmetic, which is significantly slower.
  29.  
  30. ;    Dividing is slow -- but shifting is fast, and we can select our
  31. ;    "fudge factor" to be a power of two, permitting us to use that
  32. ;    method instead.   In addition, the 386 can perform 32-bit wide
  33. ;    shifting -- and even 64-bit shifts with the following logic:
  34. ;            shdr    eax,edx,cl
  35. ;            shr    edx,cl
  36. ;    so we make sure that our "fudge factor" is a power of 2 and shift
  37. ;    it down that way.
  38. ;    Calcmand is hardcoded for a fudge factor of 2**29.
  39.  
  40.  
  41. ;                    Bert Tyler
  42. ; History since Fractint 16.0
  43. ;  (See comments with CJLT in them)
  44. ;  CJLT=Chris Lusby Taylor who has...
  45. ;
  46. ;   1. Speeded up 16 bit on 16 bit CPU
  47. ;    Minor changes, notably prescaling to fg14 before multiplying
  48. ;    instead of scaling the answer.
  49. ;    Also, I added overflow detection after adding linit, since it
  50. ;    seems this could overflow.  
  51. ;    Overall effect is about 10% faster on 386 with debugflag=8088
  52. ;   2. Speeded up 32 bit on 16 bit CPU
  53. ;    The macro `square' is totally rewritten, as is the logic for 2xy,
  54. ;    by prescaling x and y to fg31, not fg29. This allows us to do a
  55. ;    32 bit multiply in 3, not 4, 16 bit chunks while retaining full
  56. ;    fg29 accuracy.
  57. ;       Also, I removed lots of well-meaning but ineffective code handling
  58. ;    special cases of zeros and tidied up the handling of negative numbers,
  59. ;    so the routine is quite a bit shorter now and overall throughput of
  60. ;    Mandel is now over 40% faster on a 386 with debugflag=8088.
  61. ;       By the way, I was tempted to go the whole hog and replace x*x-y*y
  62. ;    by (x+y)*(x-y) to reduce 4 16-bit multiplys to 3, but it makes
  63. ;    escape detection a bit trickier. Another time, maybe.
  64. ;
  65.  
  66. ;             required for compatibility if Turbo ASM
  67. IFDEF ??version
  68. MASM51
  69. QUIRKS
  70. ENDIF
  71.  
  72. .MODEL    medium,c
  73. DGROUP          group   _DATA,_DATA2
  74.  
  75. .8086
  76.  
  77.     ; these must NOT be in any segment!!
  78.     ; this get's rid of TURBO-C fixup errors
  79.  
  80.     extrn    keypressed:far        ; this routine is in 'general.asm'
  81.     extrn    getakey:far        ; this routine is in 'general.asm'
  82.     extrn    iplot_orbit:far     ; this routine is in 'calcfrac.c'
  83.     extrn    scrub_orbit:far     ; this routine is in 'calcfrac.c'
  84.  
  85. _DATA2        segment DWORD PUBLIC 'DATA'
  86.  
  87. FUDGEFACTOR    equ    29        ; default (non-potential) fudgefactor
  88.  
  89. ; ************************ External variables *****************************
  90.  
  91.     extrn    fractype:word        ; == 0 if Mandelbrot set, else Julia
  92.     extrn    inside:word        ; "inside" color, normally 1 (blue)
  93.     extrn   outside:word            ; "outside" color, normally -1 (iter)
  94.     extrn    creal:dword, cimag:dword ; Julia Set Constant
  95.     extrn    delmin:dword        ; min increment - precision required
  96.     extrn    maxit:word        ; maximum iterations
  97.     extrn    lm:dword        ; magnitude bailout limit
  98.  
  99.     extrn    row:word, col:word    ; current pixel to calc
  100.     extrn    color:word        ; color calculated for the pixel
  101.     extrn    realcolor:word        ; color before inside,etc adjustments
  102.  
  103.     extrn    reset_periodicity:word    ; nonzero if to be reset
  104.     extrn    kbdcount:word        ; keyboard counter
  105.  
  106.     extrn    cpu:word        ; cpu type: 86, 186, 286, or 386
  107.     extrn    dotmode:word
  108.  
  109.     extrn    show_orbit:word     ; "show-orbit" flag
  110.     extrn    orbit_ptr:word        ; "orbit pointer" flag
  111.     extrn    periodicitycheck:word    ; no periodicity if zero
  112.  
  113.     public    linitx,linity        ; caller sets these
  114.     public    savedmask        ; caller sets this
  115.  
  116. ; ************************ Internal variables *****************************
  117.  
  118.         align    4
  119. x        dd    0        ; temp value: x
  120. y        dd    0        ; temp value: y
  121. absx        dd    0        ; temp value: abs(x)
  122. linitx        dd    0        ; initial value, set by calcfrac
  123. linity        dd    0        ; initial value, set by calcfrac
  124. savedmask    dd    0        ; saved values mask
  125. savedx        dd    0        ; saved values of X and Y iterations
  126. savedy        dd    0        ;  (for periodicity checks)
  127. k        dw    0        ; iteration countdown counter
  128. oldcolor    dw    0        ; prior pixel's escape time k value
  129. savedand    dw    0        ; AND value for periodicity checks
  130. savedincr    dw    0        ; flag for incrementing AND value
  131. period        db    0        ; periodicity, if in the lake
  132.  
  133. _DATA2        ends
  134.  
  135. .CODE
  136.  
  137. ; ***************** Function calcmandasm() **********************************
  138.  
  139.     public    calcmandasm
  140.  
  141. FRAME    MACRO regs
  142.     push    bp
  143.     mov    bp, sp
  144.     IRP    reg, <regs>
  145.       push    reg
  146.       ENDM
  147.     ENDM
  148.  
  149. UNFRAME MACRO regs
  150.     IRP    reg, <regs>
  151.       pop reg
  152.       ENDM
  153.     pop bp
  154.     ENDM
  155.  
  156. calcmandasm    proc
  157.     FRAME    <di,si>         ; std frame, for TC++ overlays
  158.     sub    ax,ax            ; clear ax
  159.     cmp    periodicitycheck,ax    ; periodicity checking disabled?
  160.     je    initoldcolor        ;  yup, set oldcolor 0 to disable it
  161.     cmp    reset_periodicity,ax    ; periodicity reset?
  162.     je    short initparms     ; inherit oldcolor from prior invocation
  163.     mov    ax,maxit        ; yup.    reset oldcolor to maxit-250
  164.     sub    ax,250            ; (avoids slowness at high maxits)
  165. initoldcolor:
  166.     mov    oldcolor,ax        ; reset oldcolor
  167.  
  168. initparms:
  169.     mov    ax,word ptr creal    ; initialize x == creal
  170.     mov    dx,word ptr creal+2    ;  ...
  171.     mov    word ptr x,ax        ;  ...
  172.     mov    word ptr x+2,dx     ;  ...
  173.  
  174.     mov    ax,word ptr cimag    ; initialize y == cimag
  175.     mov    dx,word ptr cimag+2    ;  ...
  176.     mov    word ptr y,ax        ;  ...
  177.     mov    word ptr y+2,dx     ;  ...
  178.  
  179.     mov    ax,maxit        ; setup k = maxit
  180.     inc    ax            ; (+ 1)
  181.     mov    k,ax            ;  (decrementing to 0 is faster)
  182.  
  183.     cmp    fractype,1        ; julia or mandelbrot set?
  184.     je    short dojulia        ; julia set - go there
  185.  
  186. ;    (Tim wants this code changed so that, for the Mandelbrot,
  187. ;    Z(1) = (x + iy) + (a + ib).  Affects only "fudged" Mandelbrots.
  188. ;    (for the "normal" case, a = b = 0, and this works, too)
  189. ;    cmp    word ptr x,0        ; Mandelbrot shortcut:
  190. ;    jne    short doeither        ;  if creal = cimag = 0,
  191. ;    cmp    word ptr x+2,0        ; the first iteration can be emulated.
  192. ;    jne    short doeither        ;  ...
  193. ;    cmp    word ptr y,0        ;  ...
  194. ;    jne    short doeither        ;  ...
  195. ;    cmp    word ptr y+2,0        ;  ...
  196. ;    jne    short doeither        ;  ...
  197. ;    dec    k            ; we know the first iteration passed
  198. ;    mov    dx,word ptr linitx+2    ; copy x = linitx
  199. ;    mov    ax,word ptr linitx    ;  ...
  200. ;    mov    word ptr x+2,dx     ;  ...
  201. ;    mov    word ptr x,ax        ;  ...
  202. ;    mov    dx,word ptr linity+2    ; copy y = linity
  203. ;    mov    ax,word ptr linity    ;  ...
  204. ;    mov    word ptr y+2,dx     ;  ...
  205. ;    mov    word ptr y,ax        ;  ...
  206.  
  207.     dec    k            ; we know the first iteration passed
  208.     mov    dx,word ptr linitx+2    ; add x += linitx
  209.     mov    ax,word ptr linitx    ;  ...
  210.     add    word ptr x,ax        ;  ...
  211.     adc    word ptr x+2,dx     ;  ...
  212.     mov    dx,word ptr linity+2    ; add y += linity
  213.     mov    ax,word ptr linity    ;  ...
  214.     add    word ptr y,ax        ;  ...
  215.     adc    word ptr y+2,dx     ;  ...
  216.     jmp    short doeither        ; branch around the julia switch
  217.  
  218. dojulia:                ; Julia Set initialization
  219.                     ; "fudge" Mandelbrot start-up values
  220.     mov    ax,word ptr x        ; switch x with linitx
  221.     mov    dx,word ptr x+2     ;  ...
  222.     mov    bx,word ptr linitx    ;  ...
  223.     mov    cx,word ptr linitx+2    ;  ...
  224.     mov    word ptr x,bx        ;  ...
  225.     mov    word ptr x+2,cx     ;  ...
  226.     mov    word ptr linitx,ax    ;  ...
  227.     mov    word ptr linitx+2,dx    ;  ...
  228.  
  229.     mov    ax,word ptr y        ; switch y with linity
  230.     mov    dx,word ptr y+2     ;  ...
  231.     mov    bx,word ptr linity    ;  ...
  232.     mov    cx,word ptr linity+2    ;  ...
  233.     mov    word ptr y,bx        ;  ...
  234.     mov    word ptr y+2,cx     ;  ...
  235.     mov    word ptr linity,ax    ;  ...
  236.     mov    word ptr linity+2,